﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Web.Mvc;

using MVCThemes;

using mvcForum.Core;
using mvcForum.Core.Abstractions.Interfaces;
using mvcForum.Core.Interfaces.Data;
using mvcForum.Core.Interfaces.Search;
using mvcForum.Core.Search;
using mvcForum.Core.Specifications;
using mvcForum.Web.Controllers;
using mvcForum.Web.Extensions;
using mvcForum.Web.Helpers;
using mvcForum.Web.ViewModels;
using mvcForum.Web.Interfaces;

namespace mvcForum.Web.Areas.Forum.Controllers {

	public class SearchController : ThemedForumBaseController {
		private readonly IConfiguration config;
		private readonly IEnumerable<ISearcher> searchers;
		private readonly ITopicRepository topicRepo;

		public SearchController(IWebUserProvider userProvider,
								IContext context,
								IConfiguration config,
								IEnumerable<ISearcher> searchers,
								ITopicRepository topicRepo)
			: base(userProvider, context) {

			this.config = config;
			this.searchers = searchers;
			this.topicRepo = topicRepo;
		}

		[ActionName("Active Topics")]
		public ActionResult ActiveTopics() {

			return View();
		}
		[ActionName("Unanswered Posts")]
		public ActionResult UnansweredPosts() {
			return RedirectToAction("Unanswered Topics");
		}

		[ActionName("Unanswered Topics")]
		public ActionResult UnansweredTopics([DefaultValue(1)]Int32 page) {
			List<Int32> accessibleForums = ForumHelper.GetAccessibleForums().Select(x => x.Id).ToList();

			// TODO: Implement paging!!
			IEnumerable<Topic> topics = this.GetRepository<Topic>().ReadMany(new TopicSpecifications.EmptyTopic())
															.Where(t => accessibleForums.Contains(t.ForumId))
															.OrderByDescending(x => x.Posted)
															.Skip((page - 1) * config.TopicsPerPage)
															.Take(config.TopicsPerPage)
															.ToList();

			UnansweredTopicsViewModel model = new UnansweredTopicsViewModel();
			model.Path = new Dictionary<String, String>();
			model.Path.Add("/forum/search/unanswered topics", ForumHelper.GetString("SearchUnanswered.Breadcrumb", null, "mvcForum.Web"));

			model.Topics = topics.Select(t => new TopicViewModel(t, new MessageViewModel[] { }, 0, 1, false, this.config.AllowQuickReply, this.config.AuthorNameSetting));

			return View(model);
		}

		public ActionResult Index() {
			return View(new SearchViewModel() { Forums = new Int32[] { } });
		}

		[HttpPost]
		public ActionResult Index(SearchViewModel model) {
			if (ModelState.IsValid) {
				// Any forums selected? If not we'll select all the forums the user has access to!
				IList<Int32> forums = (model.Forums != null ? model.Forums.ToList() : ForumHelper.GetAccessibleForums().Select(x => x.Id).ToList());

				IEnumerable<SearchResult> results = new List<SearchResult>();
				foreach (ISearcher searcher in this.searchers) {
					// Let's search!
					results = results.Concat(searcher.Search(model.Query, forums));
				}

				model.Results = new List<TopicViewModel>();
				// Any results?
				if (results.Any()) {
					IRepository<Post> postRepo = this.GetRepository<Post>();

					try {
						List<TopicViewModel> finalResults = new List<TopicViewModel>();

						foreach (SearchResult result in results.OrderByDescending(r => r.Score)) {
							// TODO: SUM on score???
							if (!finalResults.Where(vm => vm.Id == result.TopicId).Any()) {
								// TODO: Performance!!!
								Topic topic = topicRepo.ReadOneOptimizedWithPosts(result.TopicId);
								finalResults.Add(new TopicViewModel(topic, new MessageViewModel[] { }, topic.Posts.Visible(this.config).Count() - 1, config.MessagesPerPage, this.config.ShowDeletedMessages, this.config.AllowQuickReply, this.config.AuthorNameSetting));
							}
						}

						model.Results = finalResults;
						// TODO: Distinct somehow! No need to show the same topic twice!!!!
						//model.Results = results.OrderByDescending(r => r.Score).Select(x => new TopicViewModel(postRepo.Read(x.Id).Topic, config.MessagesPerPage));
					}
					catch {
						// TODO: If we should run into a hit that no longer exists, we'll end up here!!
						// TODO: Keep the index cleaned! Remove deleted content etc.!!
					}
				}
			}
			if (model.Forums == null) {
				model.Forums = new Int32[] { };
			}
			return View(model);
		}
	}
}